home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-04-23 | 12.2 KB | 492 lines | [TEXT/CWIE] |
- //
- // LEGAL NOTICE
- // ============
- //
- // You may incorporate this sample code into your applications
- // without restriction. This sample code has been provided "AS
- // IS" and the responsibility for its operation is 100% yours.
- // You are not permitted to redistribute the source as "Apple
- // sample code" after having made changes. If you're going to
- // re-distribute the source, we require that you make it clear
- // in the source that the code was descended from Apple sample
- // code, but that you've made changes.
- //
- // REVISION HISTORY
- // ================
- //
- // 06/09/95 NG last touched
- // 08/23/96 PG stolen from Nitin's old FinderDrag project
- // 04/21/97 PG pascal programs can be written in any language
- //
-
-
- #ifndef __ICONS__
- # include <Icons.h>
- #endif
-
- #ifndef __ALIASES__
- # include <Aliases.h>
- #endif
-
- #ifndef __AEREGISTRY__
- # include <AERegistry.h>
- #endif
-
- #ifndef __GESTALT__
- # include <Gestalt.h>
- #endif
-
- #ifndef __AEPACKOBJECT__
- # include <AEPackObject.h>
- #endif
-
- #ifndef __AEOBJECTS__
- # include <AEObjects.h>
- #endif
-
- #ifndef __ERRORS__
- # include <Errors.h>
- #endif
-
- #ifndef __TEXTUTILS__
- # include <TextUtils.h>
- #endif
-
- #include "GetIconSuiteFromFinder.h"
-
- #define require(x,y) do { if (!(x)) goto y; } while (0)
-
- AEDesc pFinderTarget;
-
- //----------------------------------------------------------------------------
- // FinderIsRunning
- //
- // Walk the Process Mgr list to check if the Finder is running
- //----------------------------------------------------------------------------
-
- static Boolean FinderIsRunning (void)
- {
- OSErr err;
- ProcessInfoRec pInfo;
- ProcessSerialNumber psn;
- Boolean foundIt;
-
- foundIt = false;
- psn.highLongOfPSN = 0; psn.lowLongOfPSN = kNoProcess;
-
- while ((foundIt == false) && (GetNextProcess(&psn) == noErr)) {
- pInfo.processName = NULL;
- pInfo.processAppSpec = NULL;
- pInfo.processInfoLength = sizeof(ProcessInfoRec);
-
- err = GetProcessInformation(&psn, &pInfo);
-
- if ((err == noErr)
- && (pInfo.processSignature == 'MACS')
- && (pInfo.processType == 'FNDR'))
-
- foundIt = true;
- }
-
- return foundIt;
- }
-
- //----------------------------------------------------------------------------
- // HaveScriptableFinder
- //
- // We have it if the Gestalt bit is set and the Finder is running
- //----------------------------------------------------------------------------
-
- static Boolean HaveScriptableFinder(void)
- {
- long response;
- Boolean haveScriptableFinder;
- OSErr err;
-
- haveScriptableFinder = false;
-
- err = Gestalt(gestaltFinderAttr, &response);
- require(err == noErr, Gestalt);
-
- if ((response & (1 << gestaltOSLCompliantFinder)) && (FinderIsRunning()))
- haveScriptableFinder = true;
-
- Gestalt:
- return haveScriptableFinder;
- }
-
- //----------------------------------------------------------------------------
- // SendAppleEvent
- //----------------------------------------------------------------------------
-
- static OSErr SendAppleEvent(AppleEvent *ae, AppleEvent *reply, AESendMode sendMode)
- {
- AppleEvent throwAwayReply;
- OSErr err;
-
- if (reply == NULL) {
- err = AESend(ae, &throwAwayReply, sendMode,
- kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
- if (err == noErr)
- AEDisposeDesc(&throwAwayReply);
- }
- else
- err = AESend(ae, reply, sendMode,
- kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
-
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // MakeAppleEvent
- //----------------------------------------------------------------------------
-
- static pascal OSErr MakeAppleEvent
- (AEEventClass aeClass, AEEventID aeID, AEDesc *target, AppleEvent *ae)
- {
- OSErr err = noErr;
-
- if (target->dataHandle == nil)
- {
- DescType finderSig = 'MACS';
-
- err = AECreateDesc(typeApplSignature, (Ptr) &finderSig,
- sizeof(DescType), target);
- }
-
- if (!err)
- err = AECreateAppleEvent(aeClass, aeID, target,
- kAutoGenerateReturnID, kAnyTransactionID, ae);
-
- return err;
- }
-
- //----------------------------------------------------------------------------
- // MakeSpecifierForSelection
- //----------------------------------------------------------------------------
-
- static OSErr MakeSpecifierForSelection(AEDesc *selectionSpecifier)
- {
- OSErr err;
- DescType descData;
- AEDesc keyData, nullDescriptor;
-
- nullDescriptor.descriptorType = typeNull;
- nullDescriptor.dataHandle = NULL;
-
- //
- // Make a descriptor whose type is 'typeType' and whose
- // contents are 'pSelection' (defined in FinderRegistry.h).
- // This descriptor specifies the property of the null container
- // that we are interested in--in this case, the selection.
- //
- descData = pSelection;
- err = AECreateDesc(typeType, (Ptr) &descData, sizeof(DescType), &keyData);
- require(err == noErr, AECreateDesc);
-
- err = CreateObjSpecifier(cProperty, &nullDescriptor, formPropertyID,
- &keyData, true, selectionSpecifier);
-
- AECreateDesc:
- return err;
- }
-
- //----------------------------------------------------------------------------
- // MakeSpecifierForFile
- //----------------------------------------------------------------------------
- static pascal OSErr MakeSpecifierForFile(FSSpecPtr hfsObj, AEDesc *fileSpecifier)
- {
- OSErr err;
- AEDesc nullDesc, hfsData;
- AliasHandle fileAlias;
-
- //
- // Create the file descriptor with the FSSpec passed in.
- //
- err = NewAlias(NULL, hfsObj, &fileAlias);
- require(err == noErr, NewAlias);
-
- HLock((Handle) fileAlias);
- err = AECreateDesc(typeAlias, (Ptr) *fileAlias,
- GetHandleSize((Handle) fileAlias), &hfsData);
- HUnlock((Handle) fileAlias);
- DisposeHandle((Handle) fileAlias);
- require(err == noErr, AECreateDesc);
-
- //
- // Make the object specifier with a null container
- // (i.e., "file of <null>", or just "file")
- //
- nullDesc.descriptorType = typeNull;
- nullDesc.dataHandle = NULL;
- err = CreateObjSpecifier(typeWildCard, &nullDesc,
- formAlias, &hfsData, false, fileSpecifier);
-
- AECreateDesc:
- NewAlias:
- return err;
- }
-
- //----------------------------------------------------------------------------
- // MakePropertySpecifierForSpecifier
- //----------------------------------------------------------------------------
-
- static pascal OSErr MakePropertySpecifierForSpecifier
- (DescType property, AEDesc *ofSpecifier, AEDesc *propertySpecifier)
- {
- OSErr err;
- AEDesc keyData;
-
- //
- // Create a 'type' AEDesc with the desired property
- //
- err = AECreateDesc(typeType, (Ptr) &property, sizeof(DescType), &keyData);
- require(err == noErr, AECreateDesc);
-
- //
- // With it create a property specifier for the object specifier
- // passed to us.
- //
- err = CreateObjSpecifier(cProperty, ofSpecifier,
- formPropertyID, &keyData, false, propertySpecifier);
-
- (void) AEDisposeDesc(&keyData);
- AECreateDesc:
- return err;
- }
-
- //----------------------------------------------------------------------------
- // GetSizeFromIconType
- //----------------------------------------------------------------------------
-
- static pascal Size GetSizeFromIconType (DescType iconType)
- {
- Size size = -1;
-
- switch (iconType) {
- case large8BitData:
- size = kLarge8BitIconSize;
- break;
- case large4BitData:
- size = kLarge4BitIconSize;
- break;
- case large1BitMask:
- size = kLargeIconSize;
- break;
- case small8BitData:
- size = kSmall8BitIconSize;
- break;
- case small4BitData:
- size = kSmall4BitIconSize;
- break;
- case small1BitMask:
- size = kSmallIconSize;
- break;
- }
- return size;
- }
-
-
- //----------------------------------------------------------------------------
- // BuildIconSuiteFromAEDesc
- //
- // OK, this uses the Apple Event Manager to pick the icon data out of the
- // 'ifam' AEDesc.
- //----------------------------------------------------------------------------
-
- static pascal OSErr BuildIconSuiteFromAEDesc
- (Boolean largeIcons, Handle *iconSuite, AEDesc *iconFam)
- {
- OSErr err;
- Handle suite, icon;
- AERecord rec;
- Ptr buffer;
- DescType large[3] = {large8BitData, large4BitData, large1BitMask};
- DescType small[3] = {small8BitData, small4BitData, small1BitMask};
- DescType *type, iconType, typeCode;
- long count;
- Size maxSize, size, iconSize;
- Boolean maskAdded;
- DescType maskType;
-
- maskAdded = false;
- suite = NULL;
- maxSize = kLarge8BitIconSize;
-
- if (largeIcons == true) {
- type = large;
- maskType = large1BitMask;
- }
- else {
- type = small;
- maskType = small1BitMask;
- }
-
- buffer = NewPtr(maxSize);
- require(buffer != NULL, NewPtr);
-
- err = NewIconSuite(&suite);
- require(err == noErr, NewIconSuite);
-
- err = AECoerceDesc(iconFam, typeAERecord, (AEDesc *) &rec);
- require(err == noErr, AECoerceDesc);
-
- for (count = 0; count < 3; count ++) {
- //
- // loop through the icons and grab the data from the AERecord for
- // each type of icon we're interested in.
- //
- iconType = type[count];
- size = GetSizeFromIconType(iconType);
- err = AEGetKeyPtr(&rec, iconType, iconType, &typeCode,
- buffer, maxSize, &iconSize);
-
- if (err == noErr) {
- //
- // We don't set the error code for this unless the NewHandle
- // call fails, because it's possible that the 'ifam' doesn't
- // have an icon for one that we're interested in.
- //
- icon = NewHandle(size);
-
- if (icon != NULL) {
- //
- // OK, the memory alloc succeeded and we have data. Copy
- // it into the allocated icon and add it to the suite.
- // Set atLeastOne to true, to indicate later that we did
- // in fact add at least one icon to this suite.
- //
- BlockMoveData(buffer, *icon, size);
- err = AddIconToSuite(icon, suite, iconType);
- if ((err == noErr) && (iconType == maskType))
- maskAdded = true;
- }
- else
- err = memFullErr;
- }
- }
-
- (void) AEDisposeDesc(&rec);
-
- AECoerceDesc:
- if ((err != noErr) || (maskAdded == false)) {
- //
- // There was either an error in a memory allocation, or something
- // else went wrong (like no mask was added to the suite). Get
- // rid of the partially created suite.
- //
- DisposeIconSuite(suite, true);
- suite = NULL;
- }
-
- NewIconSuite:
- DisposePtr(buffer);
-
- NewPtr:
- *iconSuite = suite;
- return err;
- }
-
- //----------------------------------------------------------------------------
- // GetIconSuiteFromFinder
- //
- // Send a GetData AE for the 'ifam'
- //----------------------------------------------------------------------------
- OSErr GetIconSuiteFromFinder (FSSpecPtr hfsObj, Handle *iconSuite)
- {
- OSErr err;
- AppleEvent finderEvent, replyEvent;
- AEDesc fileSpecifier, iconPropertySpecifier;
- DescType returnType;
- Size returnSize;
- long returnLong;
- AEDesc iconFamily;
-
- //
- // Set up our locals for easy cleanup
- //
- *iconSuite = NULL;
-
- //
- // Make sure the Finder is scriptable and is running.
- //
- err = paramErr;
- require(HaveScriptableFinder() == true, HaveScriptableFinder);
-
- //
- // Make a GetData Apple event to send to the Finder
- //
- err = MakeAppleEvent(kAECoreSuite, kAEGetData, &pFinderTarget,
- &finderEvent);
- require(err == noErr, MakeAppleEvent);
-
- //
- // Make an object specifier for the interesting file
- //
- err = MakeSpecifierForFile(hfsObj, &fileSpecifier);
- require(err == noErr, MakeSpecifierForFile);
-
- //
- // Make an icon family property specifier for the file
- //
- err = MakePropertySpecifierForSpecifier(pIconBitmap, &fileSpecifier,
- &iconPropertySpecifier);
- require(err == noErr, MakePropertySpecifierForSpecifier);
-
- //
- // Stuff it in the Apple event and send it
- //
- err = AEPutParamDesc(&finderEvent, keyDirectObject, &iconPropertySpecifier);
- require(err == noErr, AEPutParamDesc);
-
- err = SendAppleEvent(&finderEvent, &replyEvent,
- kAEWaitReply + kAECanInteract + kAECanSwitchLayer);
- require(err == noErr, SendAppleEvent);
-
- //
- // Now the Finder may have sent us an error number
- //
- err = AEGetParamPtr(&replyEvent, keyErrorNumber, typeLongInteger,
- &returnType, &returnLong, sizeof(long), &returnSize);
-
- if (err == noErr)
- err = (OSErr) returnLong;
- else if (err == errAEDescNotFound)
- err = noErr;
-
- //
- // If not, get the icon family and build an icon suite
- //
-
- if (!err)
- {
- err = AEGetParamDesc(&replyEvent, keyDirectObject, typeWildCard, &iconFamily);
- require(err == noErr, AEGetParamDesc);
- err = BuildIconSuiteFromAEDesc(true, iconSuite, &iconFamily);
- }
-
- //
- // Clean up and exit
- //
-
- (void) AEDisposeDesc(&iconFamily);
-
- AEGetParamDesc:
- (void) AEDisposeDesc(&replyEvent);
-
- SendAppleEvent:
- AEPutParamDesc:
- (void) AEDisposeDesc(&iconPropertySpecifier);
-
- MakePropertySpecifierForSpecifier:
- (void) AEDisposeDesc(&fileSpecifier);
-
- MakeSpecifierForFile:
- (void) AEDisposeDesc(&finderEvent);
-
- MakeAppleEvent:
- HaveScriptableFinder:
- return err;
- }
-